import os.path
import subprocess

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMessageBox, QWidget, QGridLayout, QLabel, QRadioButton, \
    QButtonGroup, QVBoxLayout, QGroupBox, QHBoxLayout, QPushButton

"""
Приоритет файлов конфига mos-auth-config

       /usr/lib/mos-auth/mos-auth.conf.d/*.conf
              Системные конфигурационные "drop-in" файлы

       /etc/mos-auth/mos-auth.conf
              Основной конфигурационный файл

       /etc/mos-auth/mos-auth.conf.d/*.conf
              Локальные конфигурационные "drop-in" файлы

"""

tweaker_file = '/etc/mos-auth/mos-auth.conf.d/99-tweaker.conf'


def is_installed(program: str):
    return subprocess.run(f'rpm -q {program}', shell=True, capture_output=True).stdout.decode().startswith(program)


class MosAuthorization(QWidget):

    def install_program(self, program: str):
        subprocess.run(f'dnf in -y {program}', shell=True)
        if type(self.sender()) is QPushButton:
            self.sender().setDisabled(True)

        if is_installed('mos-auth-core'):
            self.mos_authorization_groupbox.setEnabled(True)
            self.mos_auth_additional_groupbox.setEnabled(True)
            self.mos_auth_core_installed_label.setText('Пакет mos-auth-core установлен')
            self.switch_all_but_enable_authorization(self.is_mos_authorization_enabled())
        if is_installed('mos-auth-folders'):
            self.mos_auth_folders_installed_label.setText('Пакет mos-auth-folders установлен')
            self.mos_auth_folders_install_button.setDisabled(True)
        if is_installed('mos-auth-dbus-conf'):
            self.mos_auth_dbus_conf_installed_label.setText('Пакет mos-auth-dbus-conf установлен')
            self.mos_auth_dbus_conf_install_button.setDisabled(True)
        if is_installed('mos-auth-roles'):
            self.mos_auth_roles_installed_label.setText('Пакет mos-auth-roles установлен')
            self.mos_auth_roles_install_button.setDisabled(True)
        if all((is_installed('mos-auth-folders'),
                is_installed('mos-auth-dbus-conf'),
                is_installed('mos-auth-roles'))
               ):
            self.mos_auth_additional_install_all_button.setDisabled(True)

    def enable_mos_authorization(self, enable=True):
        if (self.mos_auth_enabled and enable) or (not self.mos_auth_enabled and not enable):
            return
        self.changes_output.append(f'Будет в{"ы" if not enable else ""}ключена авторизация через mos.ru')
        subprocess.run(f'mos-auth-config {"enable" if enable else "disable"}', shell=True)
        self.switch_all_but_enable_authorization(enable)
        self.mos_auth_enabled = enable

    def change_enable_enter_button(self):
        value = 'true' if self.mos_enter_button_enable_radio_button.isChecked() else 'false'
        subprocess.run(f'py-ini-config set {tweaker_file} sddm mos-auth-btn-enabled {value}', shell=True)
        if self.enter_button_enabled and self.mos_enter_button_disable_radio_button.isChecked():
            self.changes_output.append('Будет выключена кнопка входа через mos.ru')
        elif not self.enter_button_enabled and self.mos_enter_button_enable_radio_button.isChecked():
            self.changes_output.append('Будет включена кнопка входа через mos.ru')
        self.enter_button_enabled = self.mos_enter_button_enable_radio_button.isChecked()

    def change_guest_user(self):
        value = 'true' if self.guest_enable_radio_button.isChecked() else 'false'
        subprocess.run(f'py-ini-config set {tweaker_file} sddm guest-enabled {value}', shell=True)
        if self.guest_enabled and self.guest_disable_radio_button.isChecked():
            self.changes_output.append('Будет выключена гостевая учётная запись')
        elif not self.guest_enabled and self.guest_enable_radio_button.isChecked():
            self.changes_output.append('Будет включена гостевая учётная запись')
        self.guest_enabled = self.guest_enable_radio_button.isChecked()

    def change_guest_tmpfs_mount(self):
        value = 'true' if self.tmpfs_enable_radio_button.isChecked() else 'false'
        subprocess.run(f'py-ini-config set {tweaker_file} sddm guest-home-tmpfs {value}', shell=True)
        if self.guest_tmpfs_enabled and self.tmpfs_disable_radio_button.isChecked():
            self.changes_output.append('Будет выключено монтирование домашней папки гостя в tmpfs')
        elif not self.guest_tmpfs_enabled and self.tmpfs_enable_radio_button.isChecked():
            self.changes_output.append('Будет включено монтирование домашней папки гостя в tmpfs')
        self.guest_tmpfs_enabled = self.tmpfs_enable_radio_button.isChecked()

    def del_param_from_tweaker_file(self, param: str):
        subprocess.run(f'py-ini-config del {tweaker_file} sddm {param}', shell=True)
        self.sender().setDisabled(True)
        value = self.is_enabled(param)
        checkboxes = {
            'mos-auth-btn-enabled': (self.mos_enter_button_disable_radio_button, self.mos_enter_button_enable_radio_button),
            'guest-enabled': (self.guest_disable_radio_button, self.guest_enable_radio_button),
            'guest-home-tmpfs': (self.tmpfs_disable_radio_button, self.tmpfs_enable_radio_button)
        }
        variables = {
            'mos-auth-btn-enabled': self.enter_button_enabled,
            'guest-enabled': self.guest_enabled,
            'guest-home-tmpfs': self.guest_tmpfs_enabled
        }
        checkboxes[param][value].setChecked(True)
        variables[param] = value
        self.update_source_labels()

    def mos_authorization_action(self):
        self.changes_output = []
        self.enable_mos_authorization(self.mos_authorization_enable_radio_button.isChecked())
        if not os.path.isfile(tweaker_file):
            subprocess.run(f'touch {tweaker_file}', shell=True)
        self.change_enable_enter_button()
        self.change_guest_user()
        self.change_guest_tmpfs_mount()
        self.update_source_labels()
        if not self.changes_output:
            self.changes_output = ['Все указанные настройки уже применены']
        elif 'Будет выключена авторизация через mos.ru' in self.changes_output:
            self.changes_output = [
                'Будет выключена авторизация через mos.ru',
                'Остальные действия будут выключены автоматически'
            ]
        dlg = QMessageBox()
        dlg.setWindowTitle('Внимание!')
        dlg.setText('\n'.join(self.changes_output))
        dlg.exec()
        if os.stat(tweaker_file).st_size == 0:
            os.remove(tweaker_file)

    def switch_all_but_enable_authorization(self, enable: bool = True):
        if not self.is_using_tweaker_for_auth_possible():
            enable = False
        for box in (
                self.mos_enter_button_groupbox,
                self.mos_guest_groupbox,
                self.mos_tmpfs_groupbox
        ):
            box.setEnabled(enable)

    def is_mos_authorization_enabled(self):
        return os.path.isfile('/var/lib/mos-auth/enabled')

    def is_enabled(self, param: str):
        filename = self.get_mos_auth_conf_filename(param)
        # Если нашлось установленное значение в файле, вернуть
        if filename:
            return subprocess.run(f'py-ini-config get {filename} sddm {param}', shell=True,
                                    capture_output=True).stdout.decode().strip() in ('true', '1', 'yes')
        # иначе вернуть значение по умолчанию, см. man mos-auth-conf
        return False if param == 'guest-home-tmpfs' else True

    def update_source_labels(self):
        params_labels = {
            'mos-auth-btn-enabled': self.mos_enter_button_source_filename_label,
            'guest-enabled': self.mos_guest_source_filename_label,
            'guest-home-tmpfs': self.mos_tmpfs_source_filename_label
        }
        params_buttons = {
            'mos-auth-btn-enabled': self.del_enter_button_param_from_tweaker_file_button,
            'guest-enabled': self.del_guest_param_from_tweaker_file_button,
            'guest-home-tmpfs': self.del_tmpfs_param_from_tweaker_file_button
        }
        for param in params_labels.keys():
            filename = self.get_mos_auth_conf_filename(param)
            if filename:
                if filename == tweaker_file:
                    params_buttons[param].setEnabled(True)
                    tweaker_source = ' (задано твикером)'
                else:
                    params_buttons[param].setEnabled(False)
                    tweaker_source = ''
                params_labels[param].setText(f'Текущее значение получено из файла {filename}{tweaker_source}')
            else:
                params_labels[param].setText('Текущее значение (по умолчанию) не найдено в файлах конфига')

    def get_mos_auth_conf_filename(self, param='mos-auth-btn-enabled'):
        filename = None
        if os.path.isdir('/usr/lib/mos-auth/mos-auth.conf.d'):
            conf_files = [os.path.join('/usr/lib/mos-auth/mos-auth.conf.d', i) for i in
                          os.listdir('/usr/lib/mos-auth/mos-auth.conf.d') if i.endswith('.conf')]
            for file in conf_files:
                if not subprocess.run(f'py-ini-config is_set {file} sddm {param}', shell=True).returncode:
                    filename = file
        if os.path.isfile('/etc/mos-auth/mos-auth.conf'):
            file = '/etc/mos-auth/mos-auth.conf'
            if not subprocess.run(f'py-ini-config is_set {file} sddm {param}', shell=True).returncode:
                filename = file
        if os.path.isdir('/etc/mos-auth/mos-auth.conf.d'):
            conf_files = [os.path.join('/etc/mos-auth/mos-auth.conf.d', i) for i in
                          os.listdir('/etc/mos-auth/mos-auth.conf.d') if i.endswith('.conf')]
            for file in conf_files:
                if not subprocess.run(f'py-ini-config is_set {file} sddm {param}', shell=True).returncode:
                    filename = file
        if os.path.isfile(tweaker_file):
            if not subprocess.run(f'py-ini-config is_set {tweaker_file} sddm {param}', shell=True).returncode:
                filename = tweaker_file
        # if not os.path.isfile(filename):
        #     subprocess.run(f'touch {filename}', shell=True)
        return filename

    def is_using_tweaker_for_auth_possible(self):
        if os.path.isdir('/etc/mos-auth/mos-auth.conf.d'):
            conf_files = [os.path.join('/etc/mos-auth/mos-auth.conf.d', i) for i in
                          os.listdir('/etc/mos-auth/mos-auth.conf.d') if i.endswith('.conf')]
            if len(conf_files) > 0 and conf_files[-1] > tweaker_file:
                self.label_to_inform_about_file_more_than_tweaker.setText(
                    f'Найден файл {conf_files[-1]}, не позволяющий использовать твикер для изменения параметров.'
                )
                return False
        self.label_to_inform_about_file_more_than_tweaker.setText('')
        return True

    def __init__(self):
        super().__init__()

        self.mos_auth_enabled = self.is_mos_authorization_enabled()
        self.enter_button_enabled = self.is_enabled('mos-auth-btn-enabled')
        self.guest_enabled = self.is_enabled('guest-enabled')
        self.guest_tmpfs_enabled = self.is_enabled('guest-home-tmpfs')

        layout = QVBoxLayout()
        self.setLayout(layout)
        authorization_label = QLabel(f'Авторизация через портал MOS.RU')
        authorization_label.setAlignment(Qt.AlignCenter | Qt.AlignTop)
        layout.addWidget(authorization_label)

        mos_auth_core_groupbox = QGroupBox('mos-auth-core')
        mos_auth_core_groupbox_layout = QHBoxLayout()
        mos_auth_core_groupbox.setLayout(mos_auth_core_groupbox_layout)
        self.mos_auth_core_installed_label = QLabel(
            f'Пакет mos-auth-core {"не " if not is_installed("mos-auth-core") else ""}установлен'
        )
        mos_auth_core_groupbox_layout.addWidget(self.mos_auth_core_installed_label)
        self.mos_auth_core_install_button = QPushButton('Установить')
        self.mos_auth_core_install_button.clicked.connect(lambda: self.install_program("mos-auth-core"))
        mos_auth_core_groupbox_layout.addWidget(self.mos_auth_core_install_button)

        layout.addWidget(mos_auth_core_groupbox)

        self.mos_auth_additional_groupbox = QGroupBox('Дополнительные пакеты для авторизации')
        mos_auth_additional_groupbox_layout = QGridLayout()
        self.mos_auth_additional_groupbox.setLayout(mos_auth_additional_groupbox_layout)
        self.mos_auth_folders_installed_label = QLabel(
            f'Пакет mos-auth-folders {"не " if not is_installed("mos-auth-folders") else ""}установлен'
        )
        mos_auth_additional_groupbox_layout.addWidget(self.mos_auth_folders_installed_label, 0, 0)
        self.mos_auth_folders_install_button = QPushButton('Установить')
        self.mos_auth_folders_install_button.setDisabled(is_installed("mos-auth-folders"))
        self.mos_auth_folders_install_button.clicked.connect(lambda: self.install_program("mos-auth-folders"))
        mos_auth_additional_groupbox_layout.addWidget(self.mos_auth_folders_install_button, 0, 1)
        self.mos_auth_dbus_conf_installed_label = QLabel(
            f'Пакет mos-auth-dbus-conf {"не " if not is_installed("mos-auth-dbus-conf") else ""}установлен'
        )
        mos_auth_additional_groupbox_layout.addWidget(self.mos_auth_dbus_conf_installed_label, 1, 0)
        self.mos_auth_dbus_conf_install_button = QPushButton('Установить')
        self.mos_auth_dbus_conf_install_button.setDisabled(is_installed('mos-auth-dbus-conf'))
        self.mos_auth_dbus_conf_install_button.clicked.connect(lambda: self.install_program("mos-auth-dbus-conf"))
        mos_auth_additional_groupbox_layout.addWidget(self.mos_auth_dbus_conf_install_button, 1, 1)
        self.mos_auth_roles_installed_label = QLabel(
            f'Пакет mos-auth-roles {"не " if not is_installed("mos-auth-roles") else ""}установлен'
        )
        mos_auth_additional_groupbox_layout.addWidget(self.mos_auth_roles_installed_label, 2, 0)
        self.mos_auth_roles_install_button = QPushButton('Установить')
        self.mos_auth_roles_install_button.setDisabled(is_installed('mos-auth-roles'))
        self.mos_auth_roles_install_button.clicked.connect(lambda: self.install_program("mos-auth-roles"))
        mos_auth_additional_groupbox_layout.addWidget(self.mos_auth_roles_install_button, 2, 1)
        self.mos_auth_additional_install_all_button = QPushButton('Установить все пакеты')
        self.mos_auth_additional_install_all_button.clicked.connect(
            lambda: self.install_program("mos-auth-folders mos-auth-dbus-conf mos-auth-roles"))
        self.mos_auth_additional_install_all_button.setDisabled(
            all((is_installed('mos-auth-folders'),
                 is_installed('mos-auth-dbus-conf'),
                 is_installed('mos-auth-roles'))
                )
        )
        mos_auth_additional_groupbox_layout.addWidget(self.mos_auth_additional_install_all_button, 3, 0, 1, 2)

        layout.addWidget(self.mos_auth_additional_groupbox)

        self.mos_authorization_groupbox = QGroupBox('Авторизация через mos.ru')
        mos_authorization_groupbox_layout = QHBoxLayout()
        self.mos_authorization_groupbox.setLayout(mos_authorization_groupbox_layout)
        mos_authorization_checkbox_group = QButtonGroup(self)
        self.mos_authorization_enable_radio_button = QRadioButton('Включена')
        self.mos_authorization_disable_radio_button = QRadioButton('Выключить')
        mos_authorization_checkbox_group.addButton(self.mos_authorization_enable_radio_button)
        mos_authorization_checkbox_group.addButton(self.mos_authorization_disable_radio_button)
        mos_authorization_groupbox_layout.addWidget(self.mos_authorization_enable_radio_button)
        mos_authorization_groupbox_layout.addWidget(self.mos_authorization_disable_radio_button)
        if self.mos_auth_enabled:
            self.mos_authorization_enable_radio_button.setChecked(True)
        else:
            self.mos_authorization_disable_radio_button.setChecked(True)
        layout.addWidget(self.mos_authorization_groupbox)

        self.mos_enter_button_groupbox = QGroupBox('Кнопка входа через mos.ru')
        mos_enter_button_groupbox_layout = QVBoxLayout()
        self.mos_enter_button_groupbox.setLayout(mos_enter_button_groupbox_layout)
        upper_horizontal_layout = QHBoxLayout()
        self.mos_enter_button_source_filename_label = QLabel('')
        self.mos_enter_button_source_filename_label.setWordWrap(True)
        upper_horizontal_layout.addWidget(self.mos_enter_button_source_filename_label)
        self.del_enter_button_param_from_tweaker_file_button = QPushButton('Удалить')
        upper_horizontal_layout.addWidget(self.del_enter_button_param_from_tweaker_file_button)
        self.del_enter_button_param_from_tweaker_file_button.setDisabled(True)
        self.del_enter_button_param_from_tweaker_file_button.clicked.connect(
            lambda: self.del_param_from_tweaker_file('mos-auth-btn-enabled')
        )
        mos_enter_button_groupbox_layout.addLayout(upper_horizontal_layout)
        horizontal_layout = QHBoxLayout()
        mos_enter_button_checkbox_group = QButtonGroup(self)
        self.mos_enter_button_enable_radio_button = QRadioButton('Включена')
        self.mos_enter_button_disable_radio_button = QRadioButton('Выключить')
        mos_enter_button_checkbox_group.addButton(self.mos_enter_button_enable_radio_button)
        mos_enter_button_checkbox_group.addButton(self.mos_enter_button_disable_radio_button)
        horizontal_layout.addWidget(self.mos_enter_button_enable_radio_button)
        horizontal_layout.addWidget(self.mos_enter_button_disable_radio_button)
        mos_enter_button_groupbox_layout.addLayout(horizontal_layout)
        if self.enter_button_enabled:
            self.mos_enter_button_enable_radio_button.setChecked(True)
        else:
            self.mos_enter_button_disable_radio_button.setChecked(True)
        layout.addWidget(self.mos_enter_button_groupbox)

        self.mos_guest_groupbox = QGroupBox('Гостевая учётная запись')
        mos_guest_groupbox_layout = QVBoxLayout()
        self.mos_guest_groupbox.setLayout(mos_guest_groupbox_layout)
        upper_horizontal_layout = QHBoxLayout()
        self.mos_guest_source_filename_label = QLabel('')
        self.mos_guest_source_filename_label.setWordWrap(True)
        upper_horizontal_layout.addWidget(self.mos_guest_source_filename_label)
        self.del_guest_param_from_tweaker_file_button = QPushButton('Удалить')
        upper_horizontal_layout.addWidget(self.del_guest_param_from_tweaker_file_button)
        self.del_guest_param_from_tweaker_file_button.setDisabled(True)
        self.del_guest_param_from_tweaker_file_button.clicked.connect(
            lambda: self.del_param_from_tweaker_file('guest-enabled')
        )
        mos_guest_groupbox_layout.addLayout(upper_horizontal_layout)
        horizontal_layout = QHBoxLayout()
        guest_user_checkbox_group = QButtonGroup(self)
        self.guest_enable_radio_button = QRadioButton('Включена')
        self.guest_disable_radio_button = QRadioButton('Выключить')
        guest_user_checkbox_group.addButton(self.guest_enable_radio_button)
        guest_user_checkbox_group.addButton(self.guest_disable_radio_button)
        self.guest_disable_radio_button.setChecked(True)
        horizontal_layout.addWidget(self.guest_enable_radio_button)
        horizontal_layout.addWidget(self.guest_disable_radio_button)
        mos_guest_groupbox_layout.addLayout(horizontal_layout)
        if self.guest_enabled:
            self.guest_enable_radio_button.setChecked(True)
        else:
            self.guest_disable_radio_button.setChecked(True)
        layout.addWidget(self.mos_guest_groupbox)

        self.mos_tmpfs_groupbox = QGroupBox('Монтирование домашней папки гостя в tmpfs')
        mos_tmpfs_groupbox_layout = QVBoxLayout()
        self.mos_tmpfs_groupbox.setLayout(mos_tmpfs_groupbox_layout)
        upper_horizontal_layout = QHBoxLayout()
        self.mos_tmpfs_source_filename_label = QLabel('')
        self.mos_tmpfs_source_filename_label.setWordWrap(True)
        upper_horizontal_layout.addWidget(self.mos_tmpfs_source_filename_label)
        self.del_tmpfs_param_from_tweaker_file_button = QPushButton('Удалить')
        upper_horizontal_layout.addWidget(self.del_tmpfs_param_from_tweaker_file_button)
        self.del_tmpfs_param_from_tweaker_file_button.setDisabled(True)
        self.del_tmpfs_param_from_tweaker_file_button.clicked.connect(
            lambda: self.del_param_from_tweaker_file('guest-home-tmpfs')
        )
        mos_tmpfs_groupbox_layout.addLayout(upper_horizontal_layout)
        horizontal_layout = QHBoxLayout()
        tmpfs_checkbox_group = QButtonGroup(self)
        self.tmpfs_enable_radio_button = QRadioButton('Включено')
        self.tmpfs_disable_radio_button = QRadioButton('Выключить')
        tmpfs_checkbox_group.addButton(self.tmpfs_enable_radio_button)
        tmpfs_checkbox_group.addButton(self.tmpfs_disable_radio_button)
        self.tmpfs_disable_radio_button.setChecked(True)
        horizontal_layout.addWidget(self.tmpfs_enable_radio_button)
        horizontal_layout.addWidget(self.tmpfs_disable_radio_button)
        mos_tmpfs_groupbox_layout.addLayout(horizontal_layout)
        if self.guest_tmpfs_enabled:
            self.tmpfs_enable_radio_button.setChecked(True)
        else:
            self.tmpfs_disable_radio_button.setChecked(True)
        layout.addWidget(self.mos_tmpfs_groupbox)

        self.label_to_inform_about_file_more_than_tweaker = QLabel('')
        self.label_to_inform_about_file_more_than_tweaker.setWordWrap(True)
        layout.addWidget(self.label_to_inform_about_file_more_than_tweaker)

        self.update_source_labels()

        if not is_installed('mos-auth-core'):
            self.mos_auth_additional_groupbox.setDisabled(True)
            self.mos_authorization_groupbox.setDisabled(True)
            self.switch_all_but_enable_authorization(False)
        else:
            self.mos_auth_core_install_button.setDisabled(True)
            if not self.is_using_tweaker_for_auth_possible():
                self.switch_all_but_enable_authorization(False)

        if not self.mos_auth_enabled:
            self.switch_all_but_enable_authorization(False)
